// The contents of this file are subject to the Mozilla Public License Version
// 1.1
//(the "License"); you may not use this file except in compliance with the
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
//
//Software distributed under the License is distributed on an "AS IS" basis,
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
//for the specific language governing rights and
//limitations under the License.
//
//The Original Code is "The Columba Project"
//
//The Initial Developers of the Original Code are Frederik Dietz and Timo
// Stich.
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
//
//All Rights Reserved.
package org.columba.core.gui.base;

import java.awt.Component;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;

/**
 * Debugging calls to swing gui elements which are accessed outside the java
 * awt-event dispatcher thread.
 * 
 * @author fdietz
 */
public class DebugRepaintManager extends RepaintManager {

	private int tabCount = 0;

	private boolean checkIsShowing = true;

	public DebugRepaintManager() {
		super();
	}

	public DebugRepaintManager(boolean checkIsShowing) {
		super();
		this.checkIsShowing = checkIsShowing;
	}

	public synchronized void addInvalidComponent(JComponent jComponent) {
		checkThread(jComponent);
		super.addInvalidComponent(jComponent);
	}

	private void checkThread(JComponent c) {
		if (!SwingUtilities.isEventDispatchThread() && checkIsShowing(c)) {
			System.err.println("----------Wrong Thread START"); //$NON-NLS-1$
			System.err.println(getStracktraceAsString(new Exception()));
			dumpComponentTree(c);
			System.err.println("----------Wrong Thread END"); //$NON-NLS-1$
		}
	}

	private String getStracktraceAsString(Exception e) {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		PrintStream printStream = new PrintStream(byteArrayOutputStream);
		e.printStackTrace(printStream);
		printStream.flush();
		return byteArrayOutputStream.toString();
	}

	private boolean checkIsShowing(JComponent c) {
		if (this.checkIsShowing == false) {
			return true;
		} else {
			return c.isShowing();
		}
	}

	public synchronized void addDirtyRegion(JComponent jComponent, int i,
			int i1, int i2, int i3) {
		checkThread(jComponent);
		super.addDirtyRegion(jComponent, i, i1, i2, i3);
	}

	private void dumpComponentTree(Component c) {
		System.err.println("----------Component Tree"); //$NON-NLS-1$
		resetTabCount();
		for (; c != null; c = c.getParent()) {
			printTabIndent();
			System.err.println(c.toString());
			printTabIndent();
			System.err
					.println("Showing:" + c.isShowing() + " Visible: " + c.isVisible()); //$NON-NLS-2$
			incrementTabCount();
		}
	}

	private void resetTabCount() {
		this.tabCount = 0;
	}

	private void incrementTabCount() {
		this.tabCount++;
	}

	private void printTabIndent() {
		for (int i = 0; i < this.tabCount; i++) {
			System.err.print("\t");
		}
	}
}